﻿using Core.Base;
using lingopen.Foxconn.RFID.Sdk;
using Core.Com;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using Reader.RFID.Models;
using Core.Enums;
using Core.Interfaces;

namespace Reader.RFID.Forms
{


    public partial class FrmRFID : DockContentEx
    {
        public FrmRFID()
        {
            InitializeComponent();
        }
        private void btnSetting_Click(object sender, EventArgs e)
        {
            FrmConfig open = new FrmConfig();
            if (open.ShowDialog() == DialogResult.OK)
            {
                UnInit();
                Init();
            }
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            try
            {
                //清除记录前先保存阅读记录和上传记录到json文本
                if (udps != null && udps.Count > 0)
                {
                    var time = DateTime.Now;
                    string json = udps.ToJson();
                    var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"UpdateLog({time.ToString("yyyyMMddHHmmss")}).json");

                    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(path, false, Encoding.UTF8))
                    {
                        sw.Write(json);
                    }
                    rtxt.Clear();
                    listPost.Clear();
                    udps.Clear();
                    rlog.LogMessage("保存并清理成功!");
                }
            }
            catch (Exception ex)
            {
                rlog.LogMessage("Clear.Error=" + ex.Message);
            }


        }
        RichTextBoxLog rlog;
        Config config;
        private void FrmReader_Load(object sender, EventArgs e)
        {
            Init();
        }
        //public delegate void SetStateDelegate(Label lbl, string msg = "NG");
        //public void SetState(Label lbl, string msg = "NG")
        //{
        //    SetStateDelegate la = new SetStateDelegate(SetStateDe);
        //    lbl.Invoke(la, lbl, msg);
        //}
        private void SetState(Label lbl, string msg = "NG")
        {
            UpdateUI.UpdateUIControl(lbl, () =>
            {
                if (msg == "NG")
                {
                    lbl.BackColor = System.Drawing.Color.Salmon;
                }
                else
                {
                    lbl.BackColor = System.Drawing.Color.YellowGreen;
                }
                lbl.Text = msg;
            });

        }
        void UnInit()
        {
            if (PostTag != null)
                PostTag -= FrmReader_PostTag;
            if (timUpd != null)
                timUpd.Elapsed -= TimUpd_Elapsed;
            //if (UpdateControl != null)
            //    UpdateControl -= UpdateListView;
            btnStop_Click(null, null);
            UnInitReader();
        }
        /// <summary>
        /// 上传
        /// </summary> 
        private void FrmReader_PostTag(string sProEPC, string sFixEPC)
        {
            if (this.rad3.Checked)
            {
                if (sFixEPC.IsNull())
                {
                    rlog.LogError("三码绑定，未读取到治具标签");
                    return;
                }
                if (sProEPC.IsNull())
                {
                    rlog.LogError("三码绑定，未读取到产品标签");
                    return;
                }
            }
            if (this.rad24.Checked)
            {
                if (sProEPC.IsNull())
                {
                    rlog.LogError($"二码绑定，未读取到{this.iProEPCLen}位标签");
                    return;
                }
                sFixEPC = string.Empty;
            }
            if (this.rad16.Checked)
            {
                if (sFixEPC.IsNull())
                {
                    rlog.LogError($"二码绑定，未读取到{this.iFixEPCLen}位标签");
                    return;
                }
                sProEPC = string.Empty;
            }
            FCAPISend2 send = new FCAPISend2()
            {
                request_id = Guid.NewGuid().ToString().Replace("-", ""),
                host_id = config.Host_ID,
                host_ip = config.IP,
                process_name = config.ProcessName,
                wrkst_type = config.WRKST_Type,
                operation_user = "RFID",
                part_rfid_tag_sn = sProEPC,
                fixture_sn = sFixEPC,
                equipment_no = config.Host_ID
            };
            string param = "data=" + send.ToJson();
            string str2 = string.Empty;
            try
            {
                str2 = HttpHelper.POST(url: config.Url, param: param, time: 500);
            }
            catch (Exception ex)
            {
                rlog.LogError("PostTag.Error=" + ex.Message);
                SetState(lblUpd); 
                return;
            }
            string str3 = string.Empty;
            string webRes;
            if (str2.IsNotNull())
            {
                FCAPIResult fcapiResult = str2.FromJson<FCAPIResult>();
                webRes = fcapiResult.rc;
                if (fcapiResult.rc != "OK")
                {
                    rlog.LogError("PostTag.Error=" + fcapiResult.rm); 
                }
            }
            else
                webRes = "UnLoad";
            AddRowToListView(sFixEPC, sProEPC, config.Host_ID, webRes);
            if (webRes == "OK")
            {
                SetState(lblUpd, "OK");
                SoundHelper.PlayMySound("Iots/ok.wav");

                tags.Clear();
                listRead.Clear();
            }
            else
            {
                SetState(lblUpd);
                SoundHelper.PlayMySound("Iots/error.wav");
            }
        }
        static List<SaveUdp> udps = new List<SaveUdp>();
        //public delegate void AddRowItemViewDelegate(string sFixEPC, string sProEPC, string sEquipNO, string webRes);
        //private void AddRowToListView(string sFixEPC, string sProEPC, string sEquipNO, string webRes)
        //{
        //    AddRowItemViewDelegate de = new AddRowItemViewDelegate(AddRowToListViewDe);
        //    listPost.Invoke(de, sFixEPC, sProEPC, sEquipNO, webRes);

        //}
        void AddRowToListView(string sFixEPC, string sProEPC, string sEquipNO, string webRes)
        {

            UpdateUI.UpdateUIControl(listPost, () =>
            {

                udps.Add(new SaveUdp()
                {
                    FixEPC = sFixEPC,
                    ProEPC = sProEPC,
                    EquipNO = sEquipNO,
                    Res = webRes
                });
                this.listPost.Items.Add(new ListViewItem((this.listPost.Items.Count + 1).ToString())
                {
                    SubItems = {
                      sFixEPC,
                      sProEPC,
                      sEquipNO,
                      webRes,
                      DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                }
                });
                this.listPost.Items[this.listPost.Items.Count - 1].EnsureVisible();

            });


        }

        private void TimUpd_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            timUpd.Stop();
            UpdateUI.UpdateUIControl(listRead, () =>
            {
                listRead.Items.Clear();
                for (int index = 0; index < tags.Count; ++index)
                    this.listRead.Items.Add(new ListViewItem()
                    {
                        Text = (index + 1).ToString(),
                        SubItems ={
                              tags[index].epc,
                              tags[index].antNo.ToString(),
                              tags[index].count.ToString(),
                              tags[index].devNo.ToString()
                            }
                    });
            });
            //UpdateControl?.Invoke();
            EPC epcData1 = new EPC();
            EPC epcData2 = new EPC();
            string str1 = string.Empty;
            string str2 = string.Empty;
            for (int index = 0; index < tags.Count; ++index)
            {
                if (tags[index].epc.Length == this.iProEPCLen)
                {
                    if (tags[index].count > epcData1.count)
                    {
                        epcData1 = tags[index];
                        str1 = epcData1.epc;
                    }
                }
                else if (tags[index].epc.Length == this.iFixEPCLen && tags[index].count > epcData2.count)
                {
                    epcData2 = tags[index];
                    str2 = epcData2.epc;
                }
            }
            PostTag?.Invoke(str1, str2);
            tags.Clear();
        }

        static System.Timers.Timer timUpd;
        bool Init()
        {
            btnStart.Enabled = false;
            btnStop.Enabled = false;
            bool flag = false;
            //日志初始化
            if (rlog == null)
                rlog = new RichTextBoxLog(rtxt);
            config = InitConfig();
            if (config == null)
            {
                flag = false;
            }
            else
            {
                if (config.Url.IsNull())
                {
                    rlog.LogError("请在【设置】中设置URL地址!");
                    flag = false;
                }
                if (config.Port.IsNull())
                {
                    rlog.LogError("请在【设置】中设置端口号!");
                    flag = false;
                }
                if (config.Host_ID.IsNull())
                {
                    rlog.LogError("请在【设置】中设置机台码!");
                    flag = false;
                }

                this.Text = config.AppName + " " + config.Version;
                lblApi.Text = config.Url;
                lblMachineID.Text = config.Host_ID;
                lblPort.Text = config.Port;
                iProEPCLen = config.ProEPCLen24;
                iFixEPCLen = config.FixEPCLen16;
                if (timUpd == null)
                {
                    timUpd = new System.Timers.Timer(config.ReadOverTime);
                }
                else
                {
                    timUpd.Interval = config.ReadOverTime;
                }
                timUpd.Elapsed += TimUpd_Elapsed;
                PostTag += FrmReader_PostTag;

                flag = true;
            }
            //RFID设备连接状态
            if (flag && !InitReader())
            {
                flag = false;
            }
            //上传状态
            if (!flag)
            {
                btnStart.Enabled = false;
                btnStop.Enabled = false;
                rlog.LogError("初始化失败!");
            }
            else
            {
                btnStart.Enabled = true;
                btnStop.Enabled = false;
                rlog.LogMessage("准备就绪!");
                //UpdateControl += UpdateListView;
            }
            return flag;
        }
        /// <summary>
        /// 更新listview
        /// </summary>
        private void UpdateListView()
        {
            try
            {

                if (!this.InvokeRequired)
                {

                    listRead.Items.Clear();
                    for (int index = 0; index < tags.Count; ++index)
                        this.listRead.Items.Add(new ListViewItem()
                        {
                            Text = (index + 1).ToString(),
                            SubItems ={
                              tags[index].epc,
                              tags[index].antNo.ToString(),
                              tags[index].count.ToString(),
                              tags[index].devNo.ToString()
                            }
                        });
                }
                else
                    this.Invoke(new UpdateControlEventHandler(UpdateListView));

            }
            catch (Exception ex)
            {
                rlog.LogError("更新记录错误:" + ex.Message);
            }
        }

        private Config InitConfig()
        {
            //读取配置
            try
            {
                var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Iots", "Reader.RFID.json");
                if (!File.Exists(path))
                {
                    rlog.LogMessage("Reader.RFID.json文件不存在!");
                    return null;
                }
                else
                {
                    //读取json文件
                    string json = "";
                    using (System.IO.StreamReader sr = new System.IO.StreamReader(path))
                    {
                        json = sr.ReadToEnd();
                    }
                    Config config = json.FromJson<Config>();
                    return config;

                }
            }
            catch (Exception ex)
            {
                rlog.LogError($"InitConfig.Error={ex.Message}");
                return null;
            }

        }
        private bool InitReader()
        {
            try
            {
                if (config.Port.IsNull())
                {
                    rlog.LogError("请在【设置】中设置端口号!");
                    return false;
                }
                if (config.Power == null || config.Power <= 0)
                {
                    config.Power = 30;
                }
                int index = 0;
                byte[] numArray = new byte[32];
                byte[] bytes = Encoding.ASCII.GetBytes(config.Port);
                while (index < 50 && this.hDev[index] != 0)
                    ++index;
                if (index == 50)
                {
                    rlog.LogError($"{config.Port}无法访问!");
                    SetState(lblRfid);
                    return false;
                }

                PANT_CFG pantCfg = new PANT_CFG(); //设置信号强度
                pantCfg.power = new uint[4];
                uint result = (uint)config.Power;
                if (result > 30U)
                    result = 30U;
                pantCfg.power[0] = result * 10U;
                pantCfg.power[1] = result * 10U;
                pantCfg.power[2] = result * 10U;
                pantCfg.power[3] = result * 10U;

                if (NR2k.ConnectDev(ref this.hDev[index], bytes) == 0)
                {
                    //byte[] pVer = new byte[32];
                    //NR2k.GetDevVersion(this.hDev[index], pVer);
                    SetState(lblRfid, "OK");
                }
                else
                {
                    SetState(lblRfid);
                    rlog.LogError($"{config.Port}连接失败!");
                    return false;
                }

            }
            catch (Exception ex)
            {
                SetState(lblRfid);
                rlog.LogError($"启动异常:{ex.Message}");
                return false;
            }
            return true;
        }
        private bool UnInitReader()
        {
            bool flag = false;
            //断开设备
            for (int index = 0; index < 50; ++index)
            {
                if (this.hDev[index] != 0)
                {
                    NR2k.DisconnectDev(ref this.hDev[index]);
                    flag = true;
                }
            }
            if (!flag)
            {
                rlog.LogError($"断开COM失败!");
            }
            fun -= HandleData;
            this.btnStart.Enabled = true;
            this.btnStop.Enabled = false;
            return flag;
        }



        static string epc = "";
        static List<EPC> tags = new List<EPC>();
        public delegate void UpdateControlEventHandler();
        //static event UpdateControlEventHandler UpdateControl;
        static event PostTagEventHandler PostTag;
        public delegate void PostTagEventHandler(string sProEPc, string sFixEPC);

        int iProEPCLen = 24;
        int iFixEPCLen = 16;
        public void HandleData(int hDev, int cmdID, IntPtr pData, int length, IntPtr pHost)
        {
            try
            {
                epc = "";
                byte[] destination = new byte[32];
                byte[] numArray = new byte[32];
                if (length < 5 || length > 30)
                    return;
                timUpd?.Start();
                Marshal.Copy(pData, destination, 0, length);
                Marshal.Copy(pHost, numArray, 0, 16);
                for (int index = 0; index < length - 4; ++index)
                    epc += string.Format("{0:X2} ", (object)destination[index]);
                epc = epc.Replace(" ", "");
                var exsit = tags.Where(p => p.epc == epc);
                if (exsit.Any())
                {
                    var entity = tags.Where(p => p.epc == epc).FirstOrDefault();
                    entity.count++;
                    entity.antNo = (byte)((uint)destination[length - 1] + 1U);
                }
                else
                {
                    string str1 = destination[length - 3].ToString();
                    string str2 = destination[length - 2].ToString();
                    tags.Add(new EPC()
                    {
                        epc = epc,
                        antNo = destination[length - 1],
                        devNo = Encoding.Default.GetString(numArray),
                        count = (Convert.ToInt32(str1, 10) * 256 + Convert.ToInt32(str2, 10))
                    });
                }
            }
            catch (Exception ex)
            {
                rlog.LogError("读取标签异常:" + ex.Message);
            }
        }

        private int[] hDev = new int[50];
        private NR2k.HANDLE_FUN fun;

        private void btnStart_Click(object sender, EventArgs e)
        {
            Start();
        }

        private void FrmReader_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnInit();
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            Stop();
        }
        public string GetName()
        {
            return lblMachineID.Text;
        }



        public bool Start()
        {
            try
            {

                bool flag = false;
                fun += HandleData;
                for (int i = 0; i < 50; ++i)
                {
                    if (this.hDev[i] != 0)
                    {
                        NR2k.BeginInv(this.hDev[i], fun);
                        flag = true;
                    }
                }
                if (!flag)
                {
                    rlog.LogError("设备尚未连接!");
                    return false;
                }
                this.btnStart.Enabled = false;
                this.btnStop.Enabled = true;
                rlog.LogMessage("已启动");

                return true;

            }
            catch (Exception ex)
            {
                rlog.LogError($"启动异常:{ex.Message}");
                return false;
            }

        }

        public bool Stop()
        {
            try
            {

                //停止监听
                bool flag = false;
                for (int index = 0; index < 50; ++index)
                {
                    if (this.hDev[index] != 0)
                    {
                        NR2k.StopInv(this.hDev[index]);
                        flag = true;
                    }
                }
                if (!flag)
                {
                    rlog.LogError("设备尚未连接!");
                    return false;

                }
                else
                {
                    this.btnStart.Enabled = true;
                    this.btnStop.Enabled = false;
                    rlog.LogMessage("已停止");
                    return true;
                }
            }
            catch (Exception ex)
            {
                rlog.LogError($"停止异常:{ex.Message}");
                return false;
            }
        }

        public bool PowerON(Action<string> callback)
        {
            return Init();
        }

        public bool PowerOFF()
        {
            UnInit();
            return true;
        }
    }
}
